package com.keyue.service.admin.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.keyue.common.constant.Constant;
import com.keyue.common.constant.ServerResult;
import com.keyue.common.utils.TransactionHelper;
import com.keyue.domain.dto.BaseDO;
import com.keyue.domain.dto.admin.AdminMenuDO;
import com.keyue.domain.dto.admin.AdminRoleDO;
import com.keyue.domain.dto.admin.AdminRoleMenuDO;
import com.keyue.domain.vo.UserVO;
import com.keyue.domain.vo.admin.*;
import com.keyue.mapper.admin.AdminRoleMapper;
import com.keyue.service.admin.AdminMenuService;
import com.keyue.service.admin.AdminRoleMenuService;
import com.keyue.service.admin.AdminRoleService;
import com.keyue.service.admin.AdminUserRoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 角色表(AdminRole)表服务实现类
 *
 * @author makejava
 * @since 2023-08-30 17:51:48
 */
@Slf4j
@Service
public class AdminRoleServiceImpl extends ServiceImpl<AdminRoleMapper, AdminRoleDO> implements AdminRoleService {

    @Resource
    private AdminUserRoleService userRoleService;

    @Resource
    private AdminRoleMenuService roleMenuService;

    @Resource
    private AdminMenuService menuService;

    @Resource
    private TransactionHelper transactionHelper;


    /**
     * 通过ID查询单条数据
     * <p>
     * adminRoleQueryVO 主键
     *
     * @return 实例对象
     */
    @Override
    public ServerResult queryById(AdminRoleQueryVO adminRoleQueryVO) {
        if (Objects.isNull(adminRoleQueryVO.getId())) {
            return ServerResult.fail("id 不能为空");
        }
        AdminRoleDO AdminRoleDo = getById(adminRoleQueryVO.getId());
        if (Objects.isNull(AdminRoleDo)) {
            return ServerResult.success(null);
        }
        return ServerResult.success(BeanUtil.copyProperties(AdminRoleDo, AdminRoleVO.class));
    }

    /**
     * 分页查询
     *
     * @param adminRoleQueryVO 筛选条件
     * @return 查询结果
     */
    @Override
    public ServerResult list(AdminRoleQueryVO adminRoleQueryVO) {

        return ServerResult.success();
    }

    @Override
    public ServerResult listByPage(AdminRoleQueryVO queryVO) {
        LambdaQueryWrapper<AdminRoleDO> queryWrapper = buildQueryByParam(queryVO);
        Page page = new Page<>(queryVO.getPage(), queryVO.getPageSize());
        IPage<AdminRoleDO> iPage = page(page, queryWrapper);

        Page<AdminRoleResultVO> webVOPage = new Page<>();
        List<AdminRoleDO> locationStockEmptyBarcodeDOList = iPage.getRecords();
        if (CollectionUtils.isNotEmpty(locationStockEmptyBarcodeDOList)) {
            List<AdminRoleResultVO> queryVos = locationStockEmptyBarcodeDOList.stream().map(x -> {
                AdminRoleResultVO resultVO = new AdminRoleResultVO();
                BeanUtils.copyProperties(x, resultVO);
                return resultVO;
            }).collect(Collectors.toList());
            webVOPage.setRecords(queryVos);
        }
        BeanUtils.copyProperties(page, webVOPage, "records");
        return ServerResult.success(webVOPage);
    }

    /**
     * @param queryVO
     * @return
     */
    private LambdaQueryWrapper<AdminRoleDO> buildQueryByParam(AdminRoleQueryVO queryVO) {
        return new LambdaQueryWrapper<AdminRoleDO>()
                .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
                .eq(Objects.nonNull(queryVO.getLevel()), AdminRoleDO::getLevel, queryVO.getLevel())
                .eq(StringUtils.isNotBlank(queryVO.getName()), AdminRoleDO::getName, queryVO.getName())
                .eq(StringUtils.isNotBlank(queryVO.getDataScope()), AdminRoleDO::getDataScope, queryVO.getDataScope());
    }

    @Override
    public ServerResult listByLevel(Integer level) {
        return ServerResult.success(list(new LambdaQueryWrapper<AdminRoleDO>()
                .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
                .eq(Objects.nonNull(level), AdminRoleDO::getLevel, level)));
    }

    /**
     * 新增数据
     *
     * @param adminRoleVO 实例对象
     * @return 实例对象
     */
    @Override
    public ServerResult add(AdminRoleVO adminRoleVO) {
        if (Objects.nonNull(adminRoleVO.getId())) {
            adminRoleVO.setId(null);
        }
        AdminRoleDO adminRoleDo = BeanUtil.copyProperties(adminRoleVO, AdminRoleDO.class);

        save(adminRoleDo);

        return ServerResult.success();
    }

    /**
     * 修改数据
     *
     * @param adminRoleVO 实例对象
     * @return 实例对象
     */
    @Override
    public ServerResult edit(AdminRoleVO adminRoleVO) {
        //todo 校验
        if (Objects.isNull(adminRoleVO.getId())) {
            return ServerResult.fail("id 不能为空");
        }
        AdminRoleDO adminRoleDo = BeanUtil.copyProperties(adminRoleVO, AdminRoleDO.class);

        updateById(adminRoleDo);

        return ServerResult.success();
    }

    @Override
    public ServerResult authMenu(AdminAuthRoleVO adminAuthRoleVO) {
        AdminRoleDO roleDO = getById(adminAuthRoleVO.getRoleId());
        if (Objects.isNull(roleDO)) {
            return ServerResult.fail("角色不存在");
        }
        List<AdminRoleMenuDO> list = adminAuthRoleVO.getMenuIds().stream().map(x -> {
            return AdminRoleMenuDO.builder().roleId(adminAuthRoleVO.getRoleId()).menuId(x).build();
        }).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(list)) {
            return ServerResult.success();
        }
        try {
            transactionHelper.run(() -> {
                roleMenuService.remove(new LambdaQueryWrapper<AdminRoleMenuDO>().eq(AdminRoleMenuDO::getRoleId, adminAuthRoleVO.getRoleId()));
                roleMenuService.saveBatch(list);
            });
        } catch (Exception e) {
            log.error("授权异常：e:{}", e.getMessage());
        }

        return ServerResult.success();
    }

    /**
     * 通过主键删除数据
     *
     * @param adminRoleQueryVO 筛选条件
     * @return 是否成功
     */
    @Override
    public ServerResult deleteById(AdminRoleQueryVO adminRoleQueryVO) {
        List<Long> ids = adminRoleQueryVO.getIds();
        if (CollUtil.isEmpty(ids)) {
            return ServerResult.fail("ids 参数不能为空");
        }
        List<AdminRoleDO> adminRoleList = listByIds(ids);
        if (CollUtil.isEmpty(adminRoleList)) {
            return ServerResult.success();
        }
        //todo 校验是否可以逻辑删除
        LambdaUpdateWrapper<AdminRoleDO> updateWrapper = new LambdaUpdateWrapper<AdminRoleDO>()
                .in(AdminRoleDO::getId, ids)
                .set(AdminRoleDO::getEnableFlag, Constant.UNABLE_TWENTY);
        update(updateWrapper);
        return ServerResult.success();
    }


    @Override
    @Cacheable(key = "'loadPermissionByUser:' + #p0.username")
    public Collection<GrantedAuthority> mapToGrantedAuthorities(UserVO user) {
        Set<RoleSmallVO> roleSmallVOS = user.getRoles();
        if (CollectionUtils.isEmpty(roleSmallVOS)) {
            return Collections.emptyList();
        }
        Set<Long> roleIds = roleSmallVOS.stream().map(RoleSmallVO::getId).collect(Collectors.toSet());

        List<AdminRoleMenuDO> roleMenuDOS = roleMenuService.list(new LambdaQueryWrapper<AdminRoleMenuDO>().in(AdminRoleMenuDO::getRoleId, roleIds));

        if (CollectionUtils.isEmpty(roleMenuDOS)) {
            return Collections.emptyList();
        }
        Set<Long> menuIds = roleMenuDOS.stream().map(AdminRoleMenuDO::getMenuId).collect(Collectors.toSet());
        List<AdminMenuDO> menuDOList = menuService.listByIds(menuIds);
        Set<String> permissions = menuDOList.stream().filter(menuDO -> StringUtils.isNotBlank(menuDO.getPermission())).map(AdminMenuDO::getPermission).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(permissions)) {
            return Collections.emptyList();
        }
        return permissions.stream().map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());
    }
}
